/******************** (C) COPYRIGHT 2018 merafour ********************
* Author             : 冷月追风@merafour.blog.163.com
* Version            : V1.0.0
* Date               : 8/1/2019
* Description        : Device 设备扫描子线程.
********************************************************************************
* merafour.blog.163.com
* merafour@163.com
* github.com/Merafour
*******************************************************************************/
#include "scan_device.h"

#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDateTime>
#include "qiserialportbuffer.h"
#include "qiserialsync.h"
#include <QList>

QStringList scan_device::port_list;
QStringList scan_device::pull_list;
QMutex scan_device::mutex;
uint8_t scan_device::_is_run = 0;
uint8_t scan_device::_overload = 0;
uint8_t scan_device::_stop = 0;
uint8_t scan_device::_scanning = 0;
uint8_t scan_device::_exit = 0;

scan_device::scan_device(QObject *parent) : QObject(parent)
{

}
/*
 * 释放设备资源函数
*/
void scan_device::Serial_Free(const QString COM)
{
    qDebug()<<"Free COM ="<< COM;
    mutex.lock();
    for(int i = 0; i< port_list.size();++i)
    {
        QString tmp = port_list.at(i);
        //qDebug()<<"port_list tmp ="<< tmp;
        if(0==COM.compare(tmp))
        {
            port_list.removeOne(COM);
            break;
        }
    }
#if 0
    pull_list << COM; // 需等待设备拔出
#else
    pull_list.clear(); // 不等待设备拔出直接释放资源
#endif
    mutex.unlock();
}
/*
 * 发送一个扫描到的设备给主线程
*/
void scan_device::send_idle(QString port)
{
    int serach=0;
    mutex.lock();
    for(int i = 0; i< port_list.size();++i)
    {
        QString tmp = port_list.at(i);
        //qDebug()<<"tmp ="<< tmp;
        if(0==port.compare(tmp))
        {
            serach = 1;
            break;
        }
    }
    if(0==serach)
    {
        port_list << port;
        //emit sig_Serial_Idle(port);
        emit sig_scanning_update(port, Code::IDEL);
    }
    mutex.unlock();
}
/*
 * 搜索当前 port是否被使用
*/
int scan_device::serach_port(QString &port)
{
    int serach=0;
    mutex.lock();
    for(int i = 0; i< port_list.size();++i)
    {
        QString tmp = port_list.at(i);
        if(0==port.compare(tmp))
        {
            serach = 1;
            break;
        }
    }
    for(int i = 0; i< pull_list.size();++i)
    {
        QString tmp = pull_list.at(i);
        if(0==port.compare(tmp))
        {
            serach = 1;
            break;
        }
    }
    mutex.unlock();
    return serach;
}

void scan_device::doWork()
{
    int count;
    int i=0;
    QList<QSerialPortInfo> Ports;
    QString port;
    QString pull;
    uint deadline =QDateTime::currentDateTime().toTime_t();
    //uint time =QDateTime::currentDateTime().toTime_t();
    qDebug() << "Worker Run Thread : " << QThread::currentThreadId();
//    scan_port = new QiSerialSync();
//    pull_port = new QiSerialSync();
    scan_port = new QiSerialPort();
    pull_port = new QiSerialPort();
//    scan_port = new QiSerialPortBuffer();
//    pull_port = new QiSerialPortBuffer();
    // 清空 list
    port_list.clear();
    port_list << "NULL";
    pull_list.clear();
    //pull_list << "NULL";
    _is_run = 1;
    qDebug() << "_overload : " << _overload;
    // 扫描线程禁止多次创建
    if(_overload>0) return ;
    _overload = 1;
    count = 0;
    qDebug() << "new interface " << _stop;
    interface = new QiMSGSync(this, *scan_port);
    deadline =QDateTime::currentDateTime().toTime_t();
    //connect(pull_port, &user_port::errorOccurred, pull_port, &user_port::errorOccurred_slots);
    // 获取同步,扫描设备
    while (0==_stop)
    {
        count++;
        // 检测设备拔出
        mutex.lock();
        if(false == pull.isEmpty())
        {
            if(0!=pull_port->stop()) // 设备拔出
            {
                //emit
                //emit sig_progress_update(pull, Scanning::Code::PULL);
                emit sig_scanning_update(pull, Code::PULL);
                pull_list.removeOne(pull);
                pull="";
            }
        }
        //mutex.lock();
        //if(false == pull.isEmpty()) pull_list << pull;
        if(pull_list.size()>0)
        {
            pull = pull_list.at(0);
            // 移动 list,改变下一个扫描的设备
            pull_list.removeOne(pull);
            pull_list << pull;
            pull_port->OpenPortDefault(pull);
        }
        mutex.unlock();
        _is_run = 0;
        QThread::msleep(200);
        // 扫描
        _is_run = 1;
        //qDebug() << "doWork ...0";
        if(1!=_scanning)
        {
            //emit sig_progress_update(tr("watting... ")+QString::number(QDateTime::currentDateTime().toTime_t()-deadline), Scanning::Code::SCAN);
            emit sig_scanning_update(tr("watting... ")+QString::number(QDateTime::currentDateTime().toTime_t()-deadline), Code::SCAN);
            //time =QDateTime::currentDateTime().toTime_t();
            continue;
        }
        if(1==_exit) break;
        //qDebug() << "doWork ...1";
        deadline =QDateTime::currentDateTime().toTime_t();
        Ports = QSerialPortInfo::availablePorts();
        if(Ports.isEmpty())
        {
            //qDebug() << "QSerialPortInfo isEmpty" ;
            emit sig_scanning_update(tr("Don't have device ... ")+port, Code::SCAN);
            QThread::msleep(200);
            continue;
        }
        // 后去系统设备列表逐个设备获取同步
        foreach (const QSerialPortInfo &info, Ports)
        {
            QThread::msleep(200);
            //qDebug() << "doWork ...3 " << port;
            port = info.portName();
            //if(0!=info.description().compare("USB-SERIAL CH340")) continue;
            if(0==port.compare("COM1")) continue;
            //if(0==port.compare("COM5")) continue;
            //if(0==port.compare("COM6")) continue;
            //qDebug() << "doWork ...4 " << port;
            if(serach_port(port)) continue;
            //qDebug() << "doWork ...5 " << port;
            if(0!=scan_port->OpenPortDefault(port)) continue;
            //connect(my_port, &user_port::errorOccurred, my_port, &user_port::errorOccurred_slots);
            //qDebug() << port << "Scanning...";
            //emit sig_progress_update(tr("Scanning Device... ")+port, Scanning::Code::SCAN);
            //qDebug() << "Scanning Device... " << port;
            emit sig_scanning_update(tr("Scanning Device... ")+port, Code::SCAN);
            for(i=0; i<5; i++)
            {
                if(0!=interface->__scan()) break;
            }
            if(0!=interface->__scan())
            {
                // 同步失败
                //disconnect(my_port, &user_port::errorOccurred, my_port, &user_port::errorOccurred_slots);
                scan_port->close(); // my_port->close();
                continue;
            }
            //disconnect(my_port, &user_port::errorOccurred, my_port, &user_port::errorOccurred_slots);
            send_idle(port);
            //my_port->close();
            scan_port->close();
        }
        //qDebug() << "doWork ...2";
    }
    //disconnect(pull_port, &user_port::errorOccurred, pull_port, &user_port::errorOccurred_slots);

    delete interface;
    delete scan_port;
    delete pull_port;
    QThread::msleep(100);
    if(1==_exit) exit(0);
}

